/**
 * 指标跟踪中间件
 * EndoSight-UC 医疗AI系统
 *
 * 自动跟踪HTTP请求的指标数据
 */

import winston from 'winston';
import {
  trackHttpRequest,
  trackDatabaseQuery,
  trackFileUpload,
  trackScoringTask,
  trackAIInference
} from '../utils/metrics.js';

// 配置日志记录器
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.simple()
    })
  ]
});

// 生成唯一的请求ID
const generateRequestId = () => {
  return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
};

/**
 * HTTP请求指标跟踪中间件
 */
export const metricsMiddleware = (req, res, next) => {
  const startTime = Date.now();
  const requestId = generateRequestId();

  // 为请求添加唯一ID
  req.requestId = requestId;

  // 记录请求开始
  logger.info('请求开始', {
    requestId,
    method: req.method,
    url: req.url,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  // 监听响应结束
  res.on('finish', () => {
    const duration = Date.now() - startTime;
    const route = req.route ? req.route.path : req.path;

    // 跟踪HTTP请求指标
    trackHttpRequest(req.method, route, res.statusCode, duration);

    // 记录请求完成
    logger.info('请求完成', {
      requestId,
      method: req.method,
      url: req.url,
      route,
      statusCode: res.statusCode,
      duration,
      contentLength: res.get('Content-Length')
    });

    // 记录慢请求
    if (duration > 1000) {
      logger.warn('慢请求检测', {
        requestId,
        method: req.method,
        url: req.url,
        duration,
        statusCode: res.statusCode
      });
    }
  });

  next();
};

/**
 * 数据库查询指标跟踪装饰器
 */
export const trackDbQuery = (target, propertyName, descriptor) => {
  const originalMethod = descriptor.value;

  descriptor.value = async function(...args) {
    const startTime = Date.now();
    const operation = `${target.constructor.name}.${propertyName}`;

    try {
      const result = await originalMethod.apply(this, args);
      const duration = Date.now() - startTime;

      trackDatabaseQuery(operation, duration, true);
      return result;

    } catch (error) {
      const duration = Date.now() - startTime;

      trackDatabaseQuery(operation, duration, false, error.message);
      throw error;
    }
  };

  return descriptor;
};

/**
 * 异步数据库查询跟踪包装器
 */
export const withDbTracking = (operationName, fn) => {
  return async (...args) => {
    const startTime = Date.now();

    try {
      const result = await fn(...args);
      const duration = Date.now() - startTime;

      trackDatabaseQuery(operationName, duration, true);
      return result;

    } catch (error) {
      const duration = Date.now() - startTime;

      trackDatabaseQuery(operationName, duration, false, error.message);
      throw error;
    }
  };
};

/**
 * AI推理指标跟踪装饰器
 */
export const trackAIInferenceDecorator = (target, propertyName, descriptor) => {
  const originalMethod = descriptor.value;

  descriptor.value = async function(...args) {
    const startTime = Date.now();

    try {
      const result = await originalMethod.apply(this, args);
      const duration = Date.now() - startTime;

      trackAIInference(duration, true);
      return result;

    } catch (error) {
      const duration = Date.now() - startTime;

      trackAIInference(duration, false, error.message);
      throw error;
    }
  };

  return descriptor;
};

/**
 * 文件上传指标跟踪装饰器
 */
export const trackFileUploadDecorator = (target, propertyName, descriptor) => {
  const originalMethod = descriptor.value;

  descriptor.value = async function(...args) {
    const startTime = Date.now();
    let fileSize = 0;
    let success = false;
    let errorType = null;

    try {
      const result = await originalMethod.apply(this, args);
      const duration = Date.now() - startTime;

      // 尝试从结果或请求中获取文件大小
      if (result && result.fileSize) {
        fileSize = result.fileSize;
      } else if (args[0] && args[0].file && args[0].file.size) {
        fileSize = args[0].file.size;
      }

      success = true;
      trackFileUpload(fileSize, duration, true);
      return result;

    } catch (error) {
      const duration = Date.now() - startTime;
      errorType = error.constructor.name;

      trackFileUpload(fileSize, duration, false, errorType);
      throw error;
    }
  };

  return descriptor;
};

/**
 * 业务操作指标跟踪装饰器
 */
export const trackBusinessOperation = (operationType) => {
  return (target, propertyName, descriptor) => {
    const originalMethod = descriptor.value;

    descriptor.value = async function(...args) {
      const startTime = Date.now();

      try {
        const result = await originalMethod.apply(this, args);
        const duration = Date.now() - startTime;

        // 根据操作类型跟踪不同的业务指标
        switch (operationType) {
          case 'scoring_task':
            trackScoringTask('completed', duration);
            break;
          case 'scoring_error':
            trackScoringTask('error');
            break;
          case 'file_upload':
            // 文件上传已在专门的装饰器中处理
            break;
          default:
            // 通用操作跟踪
            logger.debug('业务操作完成', {
              operation: operationType,
              duration,
              success: true
            });
        }

        return result;

      } catch (error) {
        const duration = Date.now() - startTime;

        if (operationType === 'scoring_task') {
          trackScoringTask('error');
        }

        logger.error('业务操作失败', {
          operation: operationType,
          duration,
          error: error.message
        });

        throw error;
      }
    };

    return descriptor;
  };
};

/**
 * 性能监控装饰器
 */
export const monitorPerformance = (thresholdMs = 1000) => {
  return (target, propertyName, descriptor) => {
    const originalMethod = descriptor.value;

    descriptor.value = async function(...args) {
      const startTime = Date.now();
      const operation = `${target.constructor.name}.${propertyName}`;

      try {
        const result = await originalMethod.apply(this, args);
        const duration = Date.now() - startTime;

        if (duration > thresholdMs) {
          logger.warn('性能警告: 操作执行时间过长', {
            operation,
            duration,
            threshold: thresholdMs
          });
        }

        return result;

      } catch (error) {
        const duration = Date.now() - startTime;

        logger.error('操作执行失败', {
          operation,
          duration,
          error: error.message
        });

        throw error;
      }
    };

    return descriptor;
  };
};

/**
 * 增强的Express路由包装器，自动跟踪指标
 */
export const withMetricsTracking = (routeHandler, operationType = null) => {
  return async (req, res, next) => {
    const startTime = Date.now();
    const operation = operationType || `${req.method} ${req.route?.path || req.path}`;

    try {
      // 执行原始路由处理器
      await routeHandler(req, res, next);

      // 记录成功指标
      const duration = Date.now() - startTime;
      trackHttpRequest(req.method, req.route?.path || req.path, res.statusCode, duration);

      if (operationType) {
        switch (operationType) {
          case 'scoring_task':
            trackScoringTask('completed', duration);
            break;
          case 'file_upload':
            // 文件上传在专门的中间件中处理
            break;
        }
      }

    } catch (error) {
      // 记录错误指标
      const duration = Date.now() - startTime;
      trackHttpRequest(req.method, req.route?.path || req.path, 500, duration);

      if (operationType === 'scoring_task') {
        trackScoringTask('error');
      }

      logger.error('路由执行失败', {
        operation,
        duration,
        error: error.message,
        requestId: req.requestId
      });

      next(error);
    }
  };
};

export default {
  metricsMiddleware,
  trackDbQuery,
  withDbTracking,
  trackAIInferenceDecorator,
  trackFileUploadDecorator,
  trackBusinessOperation,
  monitorPerformance,
  withMetricsTracking
};